﻿using System;
using System.Collections.Generic;
using System.IO;
using MediaBrowserSL.RIA.MediaBrowserServiceReference;
using MediaBrowserSL.RIA.Tools;

namespace MediaBrowserSL.RIA.Services
{
    public class MediaRiaServices : IMediaRiaServices
    {
        delegate void GetSizeEvent(object sender, GetSizeCompletedEventArgs e);

        #region Private Member
        private MediaServiceClient client;
        private Action<IEnumerable<Media>, Exception> getMediasCallback;
        private Action<Media, Exception> createMediaCallback;
        private Action<Exception> updateMediaCallback;
        private Action<Exception> deleteMediaCallback;
        private Action<Media, Exception> createMediaItemCallback;
        private Action<IEnumerable<String>, Exception> generateImagesFromPdfBookCallback;
        private Action<Dictionary<int, double>, Exception> updateGetSizeCallback;
        #endregion

        public MediaRiaServices()
        {
            client = new MediaServiceClient();
        }

        #region GetListMediasByCategory

        public void GetListMediasByCategory(Action<IEnumerable<Media>, Exception> getMediasCallback, int idUser, int idCategory)
        {
            this.getMediasCallback = getMediasCallback;
            client.GetListMediasByCategoryCompleted += client_GetListMediasByCategoryCompleted;
            client.GetListMediasByCategoryAsync(idUser, idCategory);
        }

        void client_GetListMediasByCategoryCompleted(object sender, GetListMediasByCategoryCompletedEventArgs e)
        {
            client.GetListMediasByCategoryCompleted -= client_GetListMediasByCategoryCompleted;
            if (e.Error == null) { this.getMediasCallback(e.Result, e.Error); } else { this.getMediasCallback(null, e.Error); }
        }

        #endregion

        #region CreateMedia

        public void CreateMedia(Action<Media, Exception> createMediaCallback, Media m, User u, FileInfo imageMedia, FileInfo contentMedia)
        {
            this.createMediaCallback = createMediaCallback;

            EventHandler<GetSizeCompletedEventArgs> handler = null;
            handler = (senderSize, eSize) =>
            {
                client.GetSizeCompleted -= handler;

                double freeSize = eSize.Result[-1];

                int nbFile = 0;
                long totalSize = 0;
                if (imageMedia != null) { nbFile++; totalSize += imageMedia.Length; }
                if (contentMedia != null) { nbFile++; totalSize += contentMedia.Length; }
                m.Size = (totalSize / 1024f) / 1024f;

                if (freeSize - m.Size > 0)
                {
                    #region Convert to Byte
                    byte[] imageBytes;
                    if (imageMedia != null)
                    {
                        using (Stream str = imageMedia.OpenRead())
                        {
                            imageBytes = new Byte[str.Length];
                            str.Read(imageBytes, 0, imageBytes.Length);
                        }
                    }

                    if (contentMedia != null)
                    {
                        byte[] contentBytes;
                        using (Stream str = contentMedia.OpenRead())
                        {
                            contentBytes = new Byte[str.Length];
                            str.Read(contentBytes, 0, contentBytes.Length);
                        }
                    }
                    #endregion

                    #region Updload Files/ Create Media

                    if ((imageMedia != null) || (contentMedia != null))
                    {
                        int nbFileUploaded = 0;

                        FileServer fileServerImageMedia = new FileServer();
                        fileServerImageMedia.FileUploaded += (sender, ex) =>
                        {
                            nbFileUploaded++;
                            if (nbFile == nbFileUploaded)
                            {
                                client.CreateMediaCompleted += client_CreateMediaCompleted;
                                client.CreateMediaAsync(m, u);
                            }
                        };

                        FileServer fileServerContentMedia = new FileServer();
                        fileServerContentMedia.FileUploaded += (sender, ex) =>
                        {
                            nbFileUploaded++;
                            if (nbFile == nbFileUploaded)
                            {
                                client.CreateMediaCompleted += client_CreateMediaCompleted;
                                client.CreateMediaAsync(m, u);
                            }
                        };


                        if (imageMedia != null) { fileServerImageMedia.UploadFileAsync(u.Login + "/" + m.Category.Id + "/" + m.UrlImage, imageMedia.OpenRead()); }
                        if (contentMedia != null) { fileServerContentMedia.UploadFileAsync(u.Login + "/" + m.Category.Id + "/" + m.UrlContent, contentMedia.OpenRead()); }
                    }
                    else
                    {
                        client.CreateMediaCompleted += client_CreateMediaCompleted;
                        client.CreateMediaAsync(m, u);
                    }

                    #endregion

                }
                else
                {
                    this.createMediaCallback(null, new FullServerException());
                }
            };
            client.GetSizeCompleted += handler;
            client.GetSizeAsync(u);
        }

        void client_CreateMediaCompleted(object sender, CreateMediaCompletedEventArgs e)
        {
            client.CreateMediaCompleted -= client_CreateMediaCompleted;
            if (e.Error == null) { this.createMediaCallback(e.Result, e.Error); } else { this.createMediaCallback(null, e.Error); }
        }

        #endregion

        #region UpdateMedia

        public void UpdateMedia(Action<Exception> updateMediaCallback, Media m)
        {
            this.updateMediaCallback = updateMediaCallback;
            client.UpdateMediaCompleted += client_UpdateMediaCompleted;
            client.UpdateMediaAsync(m);
        }

        void client_UpdateMediaCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            client.UpdateMediaCompleted -= client_UpdateMediaCompleted;
            this.updateMediaCallback(e.Error);
        }

        #endregion

        #region DeleteMedia

        public void DeleteMedia(Action<Exception> deleteMediaCallback, Media m, User u)
        {
            this.deleteMediaCallback = deleteMediaCallback;
            client.DeleteMediaCompleted += client_DeleteMediaCompleted;
            client.DeleteMediaAsync(m, u);
        }

        void client_DeleteMediaCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            client.DeleteMediaCompleted -= client_DeleteMediaCompleted;
            this.deleteMediaCallback(e.Error);
        }

        #endregion

        #region CreateMediaItem

        public void CreateMediaItem(Action<Media, Exception> createMediaItemCallback, Media mediaItem, Media mediaParent, User u, FileInfo imageMedia, FileInfo contentMedia)
        {
            this.createMediaItemCallback = createMediaItemCallback;

            EventHandler<GetSizeCompletedEventArgs> handler = null;
            handler = (senderSize, eSize) =>
            {
                client.GetSizeCompleted -= handler;

                double freeSize = eSize.Result[-1];

                int nbFile = 0;
                long totalSize = 0;
                if (imageMedia != null) { nbFile++; totalSize += imageMedia.Length; }
                if (contentMedia != null) { nbFile++; totalSize += contentMedia.Length; }
                mediaItem.Size = (totalSize / 1024f) / 1024f;

                if (freeSize - mediaItem.Size > 0)
                {
                    #region Convert to Byte
                    byte[] imageBytes;
                    if (imageMedia != null)
                    {
                        using (Stream str = imageMedia.OpenRead())
                        {
                            imageBytes = new Byte[str.Length];
                            str.Read(imageBytes, 0, imageBytes.Length);
                        }
                    }

                    if (contentMedia != null)
                    {
                        byte[] contentBytes;
                        using (Stream str = contentMedia.OpenRead())
                        {
                            contentBytes = new Byte[str.Length];
                            str.Read(contentBytes, 0, contentBytes.Length);
                        }
                    }
                    #endregion

                    #region Updload Files/ Create Media

                    if ((imageMedia != null) || (contentMedia != null))
                    {
                        int nbFileUploaded = 0;

                        FileServer fileServerImageMedia = new FileServer();
                        fileServerImageMedia.FileUploaded += (sender, ex) =>
                        {
                            nbFileUploaded++;
                            if (nbFile == nbFileUploaded)
                            {
                                client.CreateMediaItemCompleted += client_CreateMediaItemCompleted;
                                client.CreateMediaItemAsync(mediaItem, mediaParent, u);
                            }
                        };

                        FileServer fileServerContentMedia = new FileServer();
                        fileServerContentMedia.FileUploaded += (sender, ex) =>
                        {
                            nbFileUploaded++;
                            if (nbFile == nbFileUploaded)
                            {
                                client.CreateMediaItemCompleted += client_CreateMediaItemCompleted;
                                client.CreateMediaItemAsync(mediaItem, mediaParent, u);
                            }
                        };

                        if (imageMedia != null) { fileServerImageMedia.UploadFileAsync(u.Login + "/" + mediaItem.Category.Id + "/" + mediaItem.UrlImage, imageMedia.OpenRead()); }
                        if (contentMedia != null) { fileServerContentMedia.UploadFileAsync(u.Login + "/" + mediaItem.Category.Id + "/" + mediaItem.UrlContent, contentMedia.OpenRead()); }
                    }
                    else
                    {
                        client.CreateMediaItemCompleted += client_CreateMediaItemCompleted;
                        client.CreateMediaItemAsync(mediaItem, mediaParent, u);
                    }

                    #endregion

                }
                else
                {
                    this.createMediaItemCallback(null, new FullServerException());
                }
            };
            client.GetSizeCompleted += handler;
            client.GetSizeAsync(u);

        }

        void client_CreateMediaItemCompleted(object sender, CreateMediaItemCompletedEventArgs e)
        {
            client.CreateMediaItemCompleted -= client_CreateMediaItemCompleted;
            if (e.Error == null) { this.createMediaItemCallback(e.Result, e.Error); } else { this.createMediaItemCallback(null, e.Error); }
        }

        #endregion

        #region GenerateImagesFromPdfBook

        public void GenerateImagesFromPdfBook(Action<IEnumerable<String>, Exception> generateImagesFromPdfBookCallback, String urlPdfBook, User u)
        {
            this.generateImagesFromPdfBookCallback = generateImagesFromPdfBookCallback;
            client.GenerateImagesFromPdfBookCompleted += client_GenerateImagesFromPdfBookCompleted;
            client.GenerateImagesFromPdfBookAsync(urlPdfBook, u);
        }

        void client_GenerateImagesFromPdfBookCompleted(object sender, GenerateImagesFromPdfBookCompletedEventArgs e)
        {
            client.GenerateImagesFromPdfBookCompleted -= client_GenerateImagesFromPdfBookCompleted;
            if (e.Error == null) { this.generateImagesFromPdfBookCallback(e.Result, e.Error); } else { this.generateImagesFromPdfBookCallback(null, e.Error); }
        }

        #endregion

        #region GetSize

        public void GetSize(Action<Dictionary<int, double>, Exception> updateGetSizeCallback, User u)
        {
            this.updateGetSizeCallback = updateGetSizeCallback;
            client.GetSizeCompleted += client_GetSizeCompleted;
            client.GetSizeAsync(u);
        }

        void client_GetSizeCompleted(object sender, GetSizeCompletedEventArgs e)
        {
            client.GetSizeCompleted -= client_GetSizeCompleted;
            if (e.Error == null) { this.updateGetSizeCallback(e.Result, e.Error); } else { this.updateGetSizeCallback(null, e.Error); }
        }

        #endregion

    }
}
